import os
import time

from selenium import webdriver
from selenium.common import TimeoutException
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

from openGaussMigrate.common.base import Base


class ComBroAction(Base):
    def __init__(self, driver_p, url_p):
        """
        初始化
        :param driver_p: 浏览器驱动地址
        :param url_p: url地址
        """
        super(ComBroAction, self).__init__()
        self.driver_path = driver_p
        self.url = url_p
        self.bro = None
        self.wait_time = 10
        self.interval_time = 1

    def open(self):
        """
        打开浏览器，访问self.url
        """
        path = Service(self.driver_path)
        self.bro = webdriver.Chrome(service=path)
        self.bro.maximize_window()
        self.bro.get(self.url)

    def close(self):
        """
        关闭浏览器
        """
        self.bro.close()

    def is_found(self, *args):
        """
        判断元素是否存在
        :param args: 定位方式和定位信息，如By.ID, 'login'
        :return: 存在返回True，否则返回False
        """
        try:
            WebDriverWait(self.bro, self.wait_time, self.interval_time
                          ).until(EC.presence_of_element_located(args))
        except TimeoutException:
            return False
        else:
            return True

    def wait_ele(self, *args):
        """
        隐式等待元素显示
        :param args: 定位方式和定位信息，如By.ID, 'login'
        :return: 定位到的元素
        """
        res = WebDriverWait(self.bro, self.wait_time, self.interval_time
                            ).until(EC.presence_of_element_located(args))
        return res

    def find_ele(self, *args):
        """
        定位元素
        :param args: 定位方式和定位信息，如By.ID, 'login'
        :return: 定位到的元素
        """
        return self.bro.find_element(*args)

    def find_eles(self, *args):
        """
        定位多个元素
        :param args: 定位方式和定位信息，如By.XPATH, '//*button'
        :return: 定位到的元素列表
        """
        return self.bro.find_elements(*args)

    def input(self, xpath, value):
        """
        通过xpath定位元素并输入值value
        :param xpath: xpath路径
        :param value: 输入值
        """
        ele = self.find_ele(By.XPATH, xpath)
        ele.clear()
        ele.send_keys(value)

    def wait_input(self, xpath, value):
        """
        隐式等待，通过xpath定位元素并输入值value
        :param xpath: xpath路径
        :param value: 输入值
        """
        ele = self.wait_ele(By.XPATH, xpath)
        ele.clear()
        ele.send_keys(value)

    def click(self, xpath):
        """
        通过xpath定位元素并点击
        :param xpath: xpath路径
        """
        self.find_ele(By.XPATH, xpath).click()

    def wait_click(self, xpath):
        """
        隐式等待，通过xpath定位元素并点击
        :param xpath: xpath路径
        """
        self.wait_ele(By.XPATH, xpath).click()

    def move_to_ele(self, xpath):
        """
        通过xpath定位元素, 并移动鼠标至元素位置（可解决滚动条导致的不可见问题）
        :param xpath: xpath路径
        """
        ele = self.wait_ele(By.XPATH, xpath)
        ActionChains(self.bro).move_to_element(ele).perform()

    def switch_to_frame(self, xpath):
        """
        切换frame
        :param xpath: frame路径
        :return: 无
        """
        ele = self.find_ele(By.XPATH, xpath)
        self.bro.switch_to.frame(ele)

    def switch_to_default(self, ):
        """切换到主frame默认的"""
        self.bro.switch_to.default_content()

    def get_ele_attr(self, xpath, attr):
        """
        通过xpath定位元素, 然后元素属性值
        :param xpath: xpath路径
        :param attr: 属性名
        :return: 属性值
        """
        ele = self.wait_ele(By.XPATH, xpath)
        return ele.get_attribute(attr)

    def exec_js(self, js):
        res = self.bro.execute_script(js)
        time.sleep(3)
        return res

    def shadow_root(self, name):
        """
        定位shadow_root
        :param name: shadow_root的name或.class等
        :return: 定位到的shadow_root
        """
        return self.bro.execute_script(
            f"return document.querySelector('{name}').shadowRoot")

    def change_ele_attr(self, xpath, attr, value):
        """
        通过xpath定位元素, 并通过js修改元素属性值
        :param xpath: xpath路径
        :param attr: 属性名
        :param value: 要修改的属性值
        :return: 修改后的属性值，可用来校验修改是否成功
        """
        ele = self.wait_ele(By.XPATH, xpath)
        self.bro.execute_script(f"arguments[0].{attr} = '{value}';", ele)
        res = self.bro.execute_script(f"return arguments[0].{attr};", ele)
        return res

    def refresh(self):
        """
        刷新页面
        """
        self.bro.refresh()

    def save_img(self, img_dir, img_name):
        """
        截图并保存
        :param img_dir: 保存目录
        :param img_name: 保存图片名
        """
        img_path = os.path.join(img_dir, img_name)
        self.bro.get_screenshot_as_file(img_path)
